package com.boarsoft.boar.app.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import com.boarsoft.agent.AgentService;
import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.BaseConfig;
import com.boarsoft.boar.app.AppHandler;
import com.boarsoft.boar.app.AppInstBiz;
import com.boarsoft.boar.entity.AppInfo;
import com.boarsoft.boar.entity.AppInst;
import com.boarsoft.config.core.ConfigFileSync;
import com.boarsoft.rpc.core.RpcContext;
import com.boarsoft.soagov.spy.SvcSpy;

/**
 * 本类用于对完全遵循平台标准的应用进行操作
 * 
 * @author Mac_J
 *
 */
@Component("macRpcAppHandler")
public class StdAppHandler implements AppHandler {
	private static final Logger log = LoggerFactory.getLogger(StdAppHandler.class);

	@Autowired
	@Lazy
	@Qualifier("agentX")
	private AgentService agentX;

	@Autowired
	@Lazy
	private SvcSpy svcSpy;

	@Autowired
	private AppInstBiz appInstBiz;
	/** 自动化部署和服务治理可以调用不依赖此服务的其它方法 */
	@Autowired(required = false)
	private ConfigFileSync configFileSync;

	@Override
	public ReplyInfo<Object> sync(AppInfo app, AppInst ai, String code, byte[] bytes, String dp) throws IllegalAccessException {
		if (configFileSync == null) {
			throw new IllegalAccessException("Only config server is allowed for this method");
		}
		String addr = ai.getAddr();
		log.info("Sync config {} to app inst {}", code, addr);
		RpcContext.specify2(addr);
		try {
			// 将修改后（新的）配置内容上传至配置中心，生成新的配置文件版本
			return configFileSync.syncOne(bytes, code, dp);
		} catch (Exception e) {
			log.error("Erro on upload ");
			return new ReplyInfo<Object>(e.getMessage());
		} finally {
			RpcContext.specify2(null);
		}
	}

	@Override
	public short test(String addr) {
		if (!this.exists(addr)) {
			return AppInst.STATUS_MISSING;
		}
		RpcContext.specify2(addr);
		try {
			svcSpy.getGlobalData();
			return AppInst.STATUS_RUNNING;
		} catch (Exception e) {
			log.error("Error on get spy data from {}", addr, e);
			return AppInst.STATUS_STOPPED;
		} finally {
			RpcContext.specify2(null);
		}
	}

	@Override
	public boolean exists(String addr) {
		String[] a = addr.split(":");
		String ip = a[0];
		int port = Integer.parseInt(a[1]);
		//
		AppInst inst = appInstBiz.find(ip, port);
		addr = String.format("%s:%d", ip, BaseConfig.AGENTX_PORT);
		RpcContext.specify2(addr);
		try {
			return agentX.exists(inst.getDeployPath());
		} catch (Exception e) {
			log.error("Error on check exists via {}", addr, e);
			return false;
		} finally {
			RpcContext.specify2(null);
		}
	}
}
